package com.xhj.bigfactory.bigFactory.threadCommunication;

import java.util.Random;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import static java.lang.System.out;
import static java.lang.Thread.currentThread;

/**
 * -
 *
 * @author 周沫 @Date 2021-07-31 @Time 17:51
 */
public class ProdConsumer_BlockQueueDemo {

  private static class Data {
    private volatile boolean FLAG = true;
    AtomicInteger integer = new AtomicInteger(0);
    BlockingQueue<String> blockingQueue = null;

    public Data(BlockingQueue<String> blockingQueue) {
      this.blockingQueue = blockingQueue;
      out.println(blockingQueue.getClass().getName());
    }

    public void prod() throws Exception {
      String data = null;
      while (FLAG) {
        data = integer.incrementAndGet() + "";
        boolean offer = blockingQueue.offer(data, 500, TimeUnit.MILLISECONDS);
        if (offer == true) {
          out.println(currentThread().getName() + " prod: " + data);
        } else {
          data = integer.decrementAndGet() + "";
        }
      }
    }

    public void consume() throws Exception {
      String data = null;
      while (FLAG) {
        int time = new Random().nextInt(500);
        try {
          Thread.sleep(time);
        } catch (Exception e) {
          e.printStackTrace();
        } finally {
        }
        data = blockingQueue.take();
        out.println(currentThread().getName() + " consume: " + data);
      }
    }

    public void stop() {
      FLAG = false;
    }
  }

  public static void main(String[] args) throws Exception {
    Data data = new Data(new ArrayBlockingQueue<String>(3));
    new Thread(
            () -> {
              out.println(currentThread().getName() + ": come in...");
              try {
                data.prod();
                for (int i = 0; i < 10; i++) {}
              } catch (Exception e) {
                e.printStackTrace();
              } finally {
              }
            },
            "AAA")
        .start();
    new Thread(
            () -> {
              out.println(currentThread().getName() + ": come in...");
              try {
                data.consume();
                for (int i = 0; i < 10; i++) {}
              } catch (Exception e) {
                e.printStackTrace();
              } finally {
              }
            },
            "BBB")
        .start();
    new Thread(
            () -> {
              out.println(currentThread().getName() + ": come in...");
              try {
                Thread.sleep(2000);
              } catch (Exception e) {
                e.printStackTrace();
              } finally {
              }
              data.stop();
              out.println("\n\n\nmain say stop.");
            },
            "CCC")
        .start();
  }
}
